package org.activequant.data.util.converter;

import org.activequant.core.domainmodel.data.MarketDataEntity;
import org.activequant.core.types.TimeStamp;
import org.activequant.data.retrieval.ISeriesDataIteratorSource;

/**
 * Use this decorator to adjust timestamps of the series by a constant
 * value.<br/>
 * TimeDelayIteratorSourceDecorator&lt;T extends MarketDataEntity&lt;T&gt;&gt; extends TransformingIteratorSourceDecorator&lt;T&gt;. 
 * Holds the following associated variable:
 * <ul>
 * <li>timeDelay(long)</li>
 * </ul>
 * Holds the following inherited variables:
 * <ul>
 * <li>source(ISeriesDataIteratorSource&lt;T&gt;)</li>
 * <li>timeDelay(long)</li>
 * </ul>
 * @author Mike Kroutikov.
 *
 * @param <T>
 */
public class TimeDelayIteratorSourceDecorator<T extends MarketDataEntity<T>>  extends TransformingIteratorSourceDecorator<T> {
	/**
	 * private long timeDelay = 0;
	 */
	private long timeDelay = 0;
	/**
	 * constructs a TimeDelayIteratorSourceDecorator&lt;T extends MarketDataEntity&lt;T&gt;&gt; (extends TransformingIteratorSourceDecorator&lt;T&gt;)
	 * using the given source(ISeriesDataIteratorSource&lt;T&gt;) to set its inherited source(ISeriesDataIteratorSource&lt;T&gt;)
	 * @param source
	 */
	public TimeDelayIteratorSourceDecorator(ISeriesDataIteratorSource<T> source) {
		super(source);
	}
	
	/**
	 * Time delay to add to all data items.<br/>
	 * Sets the associated timeDelay(long) with the given val(long)
	 * @param val delay value, in nanoseconds.
	 */
	public void setTimeDelayNanos(long val) {
		timeDelay = val;
	}
	
	/**
	 * Returns time delay value.<br/>
	 * returns the associated timeDelay(long)
	 */
	public long getTimeDelayNanos() {
		return timeDelay;
	}
	/**
	 * returns the given in(T) (T extends MarketDataEntity&lt;T&gt;) after adding the associated timeDelay(long) nanoseconds to its timeStamp(TimeStamp)
	 */
	@Override
	protected T transform(T in) {
		TimeStamp timeStamp = in.getTimeStamp();
		TimeStamp newTimeStamp = new TimeStamp(timeStamp.getNanoseconds() + timeDelay);
		
		in.setTimeStamp(newTimeStamp);
		
		return in;
	}
}
